#include "seqstack.h"

#define MAX_ROW 6
#define MAX_COL 6

typedef struct Maze{
    int map[MAX_ROW][MAX_COL];
}Maze;


void MazeInit(Maze* maze){
    int map[MAX_ROW][MAX_COL]={
        { 0, 1, 0, 0, 0, 0 },
        { 0, 1, 1, 1, 0, 0 },
        { 0, 1, 1, 1, 1, 0 },
        { 0, 1, 1, 1, 0, 0 },
        { 0, 1, 1, 1, 0, 0 },
        { 0, 0, 0, 1, 0, 0 },
    };
    size_t i = 0;
    for(;i<MAX_ROW;++i){
        size_t j = 0;
        for(;j<MAX_COL;++j){
            maze->map[i][j] = map[i][j];
        }
    }
}

void MazePrint(Maze* maze){
    size_t i = 0;
    for(;i<MAX_ROW;++i){
        size_t j = 0;
        for(;j<MAX_COL;++j){
            printf("%2d ",maze->map[i][j]);
        }
        printf("\n");
    }
        printf("\n");
}


//////////////////////////////////////////////////////////////////////////////////////
//              Round1 递归版本
/////////////////////////////////////////////////////////////////////////////////////

//是否能落脚,能返回1,不能返回0
int CanStay(Maze* maze,Point pt){
    //判断点是否在地图上
    if(pt.row < 0 || pt.row >= MAX_ROW || pt.col < 0 || pt.col >= MAX_COL){
        return 0;
    }
    int value = maze->map[pt.row][pt.col];
    if(value == 1){
        return 1;
    }
    return 0;
}

void Mark(Maze* maze,Point cur){
    maze->map[cur.row][cur.col] = 2;
    return;
}

int IsExit(Maze* maze,Point cur,Point entry){
    (void)maze;
    //如果当前点到了边界,即为找到了出口,但是不能是入口点
    if(cur.row == entry.row && cur.col == entry.col){
        return  0;
    }
    if(cur.row == 0 || cur.row == MAX_ROW-1 || cur.col == 0 || cur.col == MAX_COL-1){
        return 1;
    }
    return 0;
}

void _GetPath(Maze* maze,Point cur,Point entry){
    printf("row:%d col:%d\n",cur.row,cur.col);
    //1.判断当前点是否能落脚,不能落脚直接返回
    if(!CanStay(maze,cur)){
        return;
    }
    //2.如果能落脚,标记当前点
    Mark(maze,cur);
    //3.判断当前点是否为出口点,是则直接return
    if(IsExit(maze,cur,entry)){
        //找到了出口直接返回
        printf("找到了一条出路\n");
        return;
    }
    //4.判断当前点的上下左右是否有路可走,递归判断
    Point up = cur;
    up.row -= 1;
    _GetPath(maze,up,entry);

    Point right = cur;
    right.col += 1;
    _GetPath(maze,right,entry);

    Point down = cur;
    down.row += 1;
    _GetPath(maze,down,entry);

    Point left = cur;
    left.col -= 1;
    _GetPath(maze,left,entry);
    
}

void GetPath(Maze* maze,Point entry){
    if(maze == NULL){
        return;
    }
    //使用_GetPath辅助完成递归
    _GetPath(maze,entry,entry);
}



//////////////////////////////////////////////////////////////////////////////////////
//                  Round2 使用非递归版本
/////////////////////////////////////////////////////////////////////////////////////


void GetPathByLoop(Maze* maze,Point entry){
    if(maze == NULL){
        return;
    }
    SeqStackType cur;
    //手动维护一个栈,保存走过的路径
    SeqStack stack;
    SeqStackInit(&stack);
    //1.先判断是否能落脚，能落脚，当前点入栈
    if(!CanStay(maze,entry)){
        return;
    }
    SeqStackPush(&stack,entry);
    //2.如果能落脚，标记当前点
//    Mark(maze,entry);
    //循环取栈顶元素
    while(SeqStackTop(&stack,&cur)){
        Mark(maze,cur);
        if(IsExit(maze,cur,entry)){
        printf("找到了一条出路\n");
        return;
        }

        Point up = cur;
        up.row -= 1;
        if(CanStay(maze,up)){
//            Mark(maze,up);
            SeqStackPush(&stack,up);
            continue;
        }

        Point right = cur;
        right.col += 1;
        if(CanStay(maze,right)){
//            Mark(maze,right);
            SeqStackPush(&stack,right);
            continue;
        }

        Point down = cur;
        down.row += 1;
        if(CanStay(maze,down)){
//            Mark(maze,down);
            SeqStackPush(&stack,down);
            continue;
        }

        Point left = cur;
        left.col -= 1;
        if(CanStay(maze,left)){
//            Mark(maze,left);
            SeqStackPush(&stack,left);
            continue;
        }
        SeqStackPop(&stack);
    }
}



//////////////////////////////////////////////////////////////////////////////////////
//                  以下为测试代码
/////////////////////////////////////////////////////////////////////////////////////

#if 1
#define TEST_HEADER printf("\n=========================%s=======================\n",__FUNCTION__)
void test(){
    TEST_HEADER;
    Maze maze;
    MazeInit(&maze);
    MazePrint(&maze);
    Point entry = {0,1};
    GetPath(&maze,entry);
    MazePrint(&maze);
}

void test2(){
    TEST_HEADER;
    Maze maze;
    MazeInit(&maze);
    MazePrint(&maze);
    Point entry = {0,1};
    GetPathByLoop(&maze,entry);
    MazePrint(&maze);

}

int main(){
    test();
    test2();
    return 0;
} 
#endif
